#include <matrix\gsl_matrix.h>
#include <multifit\gsl_multifit.h>
#include <test\gsl_test.h>
#include <sort\gsl_sort_vector.h>
#include <vector\gsl_vector.h>

#include <iostream>
#include "stdio.h"

#include "lip.h"

#include "ddas_client_setup.h"
#include "ddas_globals.h"
#include "ddas_debug.h"

using namespace std;


/**
* @author Max Rupplin
* @date 5-15-08
* @param matrix The matrix to be printed
* @param rows The last row to be printed 
* @param cols The last column to be printed
*
* 'ddas_print_gsl_matrix' prints a portion of a matrix ending at 'rows' and 'cols'
*/ 
void ddas_print_gsl_matrix(gsl_matrix* matrix, int rows, int cols)
{
	for(int r=0; r<rows; r++)
	{
		for(int c=0; c<cols; c++)
		{
			cerr<<" | "<<gsl_matrix_get(matrix, r, c);
		}

		cerr<<" |"<<endl;
	}

	cerr<<""<<endl;
}

/**
* @author Max Rupplin
* @date 5-15-08
* @param matrix The matrix to be printed
*
* 'ddas_print_gsl_matrix' prints the entirety of a matrix
*/
void ddas_print_gsl_matrix(gsl_matrix* matrix)
{
	int rows    = (int)matrix->size1;
	int columns = (int)matrix->size2;

	for(int r=0; r<rows; r++)
	{
		for(int c=0; c<columns; c++)
		{
			cerr<<" | "<<gsl_matrix_get(matrix, r, c);
		}

		cerr<<" |"<<endl;
	}

	cerr<<""<<endl;
}


/** 
* @author Max Rupplin
* @date 5-15-08
* @param vector The gsl_vector to be printed
* @param dimension The starting index from which to start printing
*
* 'ddas_print_gsl_vector_h' prints a portion of a gsl_vector horizontally, starting at 'dimension'
*/ 
void ddas_print_gsl_vector_h(gsl_vector* vector, int dimension)
{
	for(int i=0; i<dimension; i++)
	{
		cerr<<" | "<<gsl_vector_get(vector, i);
	}

	cerr<<" |"<<endl;
}


/**
* @author Max Rupplin
* @date 5-15-08
* @param vector The gsl_vector to be printed
* @param dimension The starting index from which to start printing
*
* 'ddas_print_gsl_vector_v' prints a portion of a gsl_vector vertically, starting at 'dimension'
*/ 
void ddas_print_gsl_vector_v(gsl_vector* vector, int dimension)
{
	for(int i=0; i<dimension; i++)
	{
		cerr<<"----"<<endl<<gsl_vector_get(vector, i)<<""<<endl;
	}

	cerr<<"----"<<endl;
}


/**
* @author Max Rupplin
* @date 5-15-08
* @param vector The gsl_vector to be printed
*
* 'ddas_print_gsl_vector_h' prints a gsl_vector horizontally
*/ 
void ddas_print_gsl_vector_h(gsl_vector* vector)
{
	int dimension = (int)vector->size;

	for(int i=0; i<dimension; i++)
	{
		cerr<<" | "<<gsl_vector_get(vector, i);
	}

	cerr<<" |"<<endl;
}


/**
* @author Max Rupplin
* @date 5-15-08
* @param vector The gsl_vector to be printed
*
* 'ddas_print_gsl_vector_v' prints a gsl_vector vertically
*/ 
void ddas_print_gsl_vector_v(gsl_vector* vector)
{
	int dimension = (int) vector->size;

	for(int i=0; i<dimension; i++)
	{
		cerr<<"----"<<endl<<gsl_vector_get(vector, i)<<""<<endl;
	}

	cerr<<"----"<<endl;
}


/** 
* @author Max Rupplin
* @date 5-15-08
* @param coeffs The regression coefficients for this iteration
* @param covariance The variance-covariance matrix for this iteration
* @param chi_squared The SSE/chi^2 value for this iteration
* @param iteration The current iteration
*
* 'ddas_print_statistical_data' prints regression coefficients, covariance matrix and SSE (chi_squared) for a given iteration
*/
void ddas_print_statistical_data(gsl_vector* coeffs, gsl_matrix* covariance, double* chi_squared, verylong* iteration)
{
	cerr<<"--------------------------------------"<<endl;
	cerr<<"STATISTICAL DATA FOR ITERATION #";
	zwritestderr(*iteration);
	cerr<<":"<<endl<<endl;

	//covariance matrix
	cerr<<"COVARIANCE MATRIX:"<<endl;
	ddas_print_gsl_matrix(covariance);
	cerr<<""<<endl;

	//regression coefficients
	cerr<<"REGRESSION COEFFICIENTS:"<<endl;
	ddas_print_gsl_vector_h(coeffs);
	cerr<<""<<endl;

	//SSE / chi_squared
	cerr<<"CHI^2:\n | "<<*chi_squared<<" |"<<endl;

	cerr<<"--------------------------------------\n"<<endl;
}


/** 
* @author Max Rupplin
* @date 5-15-08
* @param src A gsl_vector containing the values to be printed
* @param indices A gsl_vector containing the indices we which to print
*
* 'ddas_print_gsl_vector_values_at_specified_indices' prints values in 'src' of indices specified by 'indices'
*/ 
void ddas_print_gsl_vector_values_at_specified_indices(gsl_vector* src, gsl_vector* indices)
{
	try
	{
		for(int i=0; i<((int)indices->size); i++)
		{
			size_t current_src_index = (size_t)gsl_vector_get(indices,i);

			if(current_src_index<0 || current_src_index>=src->size) throw i;

			cerr<<"Index #"<<i<<" = "<<gsl_vector_get(src, current_src_index)<<""<<endl; 
		}
	}
	catch(int errant_index)
	{
		cerr<<"ddas_print_gsl_vector_values_at_indices:\nIndex #"<<errant_index<<" does not exist."<<endl;
	}
}


/** 
* @author Max Rupplin
* @date 5-15-08
* 
* 'ddas_print_global_vars' prints the global variables - useful for debugging
*/
void ddas_print_global_vars()
{
	cerr<<"GLOBAL VARIABLES------------------------------"<<endl;
	cerr<<"starting_value:"; zwritelnstderr(starting_value);
	cerr<<"ending_value:"; zwritelnstderr(ending_value);
	cerr<<"results_to_return:"<<results_to_return<<endl;
	cerr<<"total_results:"; zwritelnstderr(total_result_count);
	cerr<<"row_count:"<<row_count<<endl;
	cerr<<"dependent_var_count:"<<dependent_var_count<<endl;
	cerr<<"independent_var_count:"<<independent_var_count<<endl;
	cerr<<"----------------------------------------------"<<endl;
}


/** 
* @author Max Rupplin
* @date 5-15-08
* @param result_set A DDAS_CLIENT_RESULT_SET which contains one or more DDAS_CLIENT_RESULTs
*
* 'ddas_print_client_result_set' prints out every DDAS_CLIENT_RESULT in a DDAS_CLIENT_RESULT_SET
*/
void ddas_print_client_result_set(DDAS_CLIENT_RESULT_SET* result_set)
{
	#ifdef DEBUG_MODE
	cerr<<"ddas_print_client_result_set called."<<endl;
	#endif

	if(result_set->size==0) 
	{
		#ifdef DEBUG_MODE
		cerr<<"ddas_print_client_result_set reports that there are no results to print."<<endl;
		#endif 

		return;
	}

	for(int i=0; i<(result_set->size); i++)
	{
		ddas_print_client_result( &(result_set->result[i]) ); 

		/**DDAS_CLIENT_RESULT current=result_set->result[i];

		cerr<<"Iteration: "; zwritestderr(current.definition_number); cerr<<"."<<endl;
		cerr<<"SSE: "<< current.sse <<"."<<endl;
		cerr<<"Regression Coefficients:"<<endl;

		for(unsigned int j=0; j<(current.regression_coefficients->size); j++)
		{	
			double d=gsl_vector_get(current.regression_coefficients, j);
			cerr<<d<<" ";
		}

		cerr<<endl;*/
	}

	#ifdef DEBUG_MODE
	cerr<<"ddas_print_client_result_set returning."<<endl;
	#endif
}

/** 
* @author Max Rupplin
* @date 5-15-08
* @param result A single DDAS_CLIENT_RESULT result
*
* 'ddas_print_client_result' prints out a single DDAS_CLIENT_RESULT
*/ 
void ddas_print_client_result(DDAS_CLIENT_RESULT* result)
{
	cerr<<endl;

	cerr<<"Iteration="; zwritelnstderr(result->definition_number);
	cerr<<"SSE="<<result->sse<<endl;	

	for(unsigned int i=0; i<result->regression_coefficients->size; i++)
	{
		cerr<<"rc #"<<i<<": "<< gsl_vector_get( result->regression_coefficients, i ) <<endl;
	}

	cerr<<endl;
}
